<template>
  <div class="v-week-picker" ref="weekPickerObj">
    <div class="v-week-picker-header">
      <a href="javascript:;" class="iconfont icon-arrow-right-line v-week-picker-header__prev" @click="prevOrNextWeekChange(-1)"></a>
      <span class="v-week-picker-header__label" @click="showDropList=!showDropList">
        <template v-if="weekValue.length>1">
          {{weekValue[0]}}年 第{{weekValue[1]}}周
        </template>
      </span>
      <a href="javascript:;" class="iconfont icon-arrow-right-line v-week-picker-header__next" @click="prevOrNextWeekChange(1)"></a>
    </div>
    <div v-show="showDropList" class="v-week-picker-droplist" :style="{top:droplistTop+'px'}" @click="showDropList=false">
      <div class="v-week-picker-droplist-header" @click.stop="showDropList=true">
        <div class="v-week-picker-droplist-yearhandler">
          <a href="javascript:;" class="iconfont icon-arrow-right-line v-week-picker-header__prev" @click="yearChangeHandler(-1)"></a>
          {{selYear}}
          <a href="javascript:;" class="iconfont icon-arrow-right-line v-week-picker-header__next" @click="yearChangeHandler(1)"></a>
        </div>
        <div class="v-week-picker-droplist-monthhandler" ref="monthList">
          <a href="javascript:;" class="month-item" v-for="(item,index) in monthList" :key="index" :class="[{active:+selMonth===index},{disabled:!checkMonthEnable(index)}]" @click="monthChangeHandler(index)">{{item}}</a>
        </div>
      </div>
      <div class="v-week-picker-droplist-content" @click.stop="showDropList=true">
        <ul class="calendar-row calendar-row-header">
          <li class="week-value"></li>
          <li v-for="(item,index) in weekList" :key="index">{{item}}</li>
        </ul>
        <ul class="calendar-row calendar-row-body" v-for="(item,index) in calendayArr" :key="index" :class="{active:JSON.stringify(weekValue)===JSON.stringify(item.weekVal)}" @click.stop="weekChangeHandler(item)">
          <li class="week-value">{{item.weekVal[1]}}周</li>
          <li class="day-cell" v-for="(item1,index1) in item.dayList" :key="index1" :class="{disabled:(index===0 && item1.dateNum > 10) || (index>2 && item1.dateNum < 10)}">
            <template v-if="isToday(item1.date)">
              今
            </template>
            <template v-else>
              {{item1.dateNum}}
            </template>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
/*
   功能模块  周选择器
   创建人    zgf
   更新时间  2019/12/24
   页面参数  
   备注      
*/
import DateUtil from './dateUtil.js'
export default {
  name: 'VWeekPicker',
  props: {
    value: {
      type: Array,
      default() {
        return []
      }
    },
    maxWeek: {
      type: Array,
      default() {
        return []
      }
    },
    maxMsg:{
      type:String,
      default:''
    },
    minWeek: {
      type: Array,
      default() {
        return []
      }
    },
    minMsg:{
      type:String,
      default:''
    }
  },
  data() {
    return {
      todayDate: new Date().getTime(),
      droplistTop: 0,
      showDropList: false,
      weekValue: [],
      selYear: 2019,
      selMonth: 10,
      monthList: [
        '1月',
        '2月',
        '3月',
        '4月',
        '5月',
        '6月',
        '7月',
        '8月',
        '9月',
        '10月',
        '11月',
        '12月'
      ],
      weekList: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
      calendayArr: []
    }
  },
  computed: {
    scroller() {
      return DateUtil.getScrollEventTarget(this.$el);
    }
  },
  watch: {
    value: {
      deep: true,
      handler(newVal) {
        this.weekValue = newVal
        this.calendarRender()
      }
    },
    weekValue: {
      deep: true,
      handler(newVal) {
        this.$emit('input', newVal)
      }
    },
    selMonth(newVal) {
      this.$refs.monthList.scrollLeft = 44 * newVal - 100
    },
    showDropList(newVal) {
      if (newVal) {
        this.$nextTick(() => {
          this.$refs.monthList.scrollLeft = 44 * this.selMonth - 100
          this.updateOffsetTop()
        })
        this.scroller.addEventListener('scroll',this.onScroll)
      }else{
        this.scroller.removeEventListener('scroll',this.onScroll)
      }
    }
  },
  mounted() {
    this.setDefaultVal()
    this.yearAndMonthRender()
    this.calendarRender()
    document.addEventListener('click',(e)=>{
      let ignNames = ['v-week-picker-header','v-week-picker-header__label','iconfont icon-arrow-right-line v-week-picker-header__next','iconfont icon-arrow-right-line v-week-picker-header__prev']
      if(ignNames.indexOf(e.target.className)!==-1){
        return false
      }
      this.showDropList = false
    })
  },
  methods: {
    //判断某日期是否是今天
    isToday(date){
      let nowStr = DateUtil.formatDate(new Date(),'yyyyMMdd')
      let dateStr = DateUtil.formatDate(date,'yyyyMMdd')
      return nowStr === dateStr
    },
    //计算top值
    updateOffsetTop(){
      let rect = this.$refs.weekPickerObj.getBoundingClientRect()
      this.droplistTop =rect.y ? rect.y + rect.height : rect.top + rect.height
    },
    //滚动时重新计算top值
    onScroll(){
      this.updateOffsetTop()
    },
    //输入值如果为空，默认当前周
    setDefaultVal() {
      this.weekValue = this.value
      if (!this.value || this.value.length < 2) {
        this.weekValue = DateUtil.getWeekByDate(new Date())
      }
      this.selYear = this.weekValue[0]
      let weekTimeObj = DateUtil.getStartAndEndDateByWeekNum(this.weekValue)
      this.selMonth = new Date(weekTimeObj.startDate).getMonth()
    },
    //年月条条渲染
    yearAndMonthRender() {},
    //日历列表渲染
    calendarRender() {
      let dayOneDateObj = new Date(
        this.selYear + '/' + (+this.selMonth + 1) + '/1'
      )
      let firstDay = dayOneDateObj.getDay()
      firstDay = firstDay === 0 ? 7 : firstDay
      let begin = dayOneDateObj.getTime() - (firstDay - 1) * 60 * 60 * 1000 * 24
      let month2 = DateUtil.isLeapYear(this.selYear) ? 29 : 28 //2月平年28天，闰年29天
      let lastDayArr = [31, month2, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
      let lastDayObj = new Date(
        this.selYear +
          '/' +
          (+this.selMonth + 1) +
          '/' +
          lastDayArr[this.selMonth]
      )
      let lastDayWeek = lastDayObj.getDay()
      lastDayWeek = lastDayWeek === 0 ? 7 : lastDayWeek
      let end = lastDayObj.getTime() + (7 - lastDayWeek) * 60 * 60 * 1000 * 24
      let oneWeek = 7 * 24 * 60 * 60 * 1000
      let oneDay = 1 * 24 * 60 * 60 * 1000
      let calendayArr = []
      for (var i = begin; i < end; i += oneWeek) {
        let l = i + 6 * 24 * 60 * 60 * 1000
        let weekDaysArr = []
        for (var j = i; j <= l; j += oneDay) {
          let dd = new Date(j)
          weekDaysArr.push({
            dateNum: dd.getDate(),
            date: dd
          })
        }
        calendayArr.push({
          weekVal: DateUtil.getWeekByDate(new Date(i)),
          dayList: weekDaysArr
        })
      }
      this.calendayArr = calendayArr
    },
    //上一周，下一周切换
    prevOrNextWeekChange(step) {
      let oneWeek = 7 * 24 * 60 * 60 * 1000
      let firstDay = DateUtil.getStartAndEndDateByWeekNum(this.weekValue)
        .startDate
      firstDay = new Date(firstDay).getTime()
      let resultWeek = []
      let resultYear = 2019;
      let resultMonth = 12;
      if (step < 0) {
        //上一周
        let prevWeek = new Date(firstDay - oneWeek)
        resultYear = prevWeek.getFullYear()
        resultMonth = prevWeek.getMonth()
        resultWeek = DateUtil.getWeekByDate(prevWeek)
      } else {
        //下一周
        let nextWeek = new Date(firstDay + oneWeek)
        resultYear = nextWeek.getFullYear()
        resultMonth = nextWeek.getMonth()
        resultWeek = DateUtil.getWeekByDate(nextWeek)
      }
      if (!this.checkWeekEnable(resultWeek,true)) {
        return false
      }
      this.selYear = resultYear
      this.selMonth = resultMonth
      this.weekValue = resultWeek
      this.calendarRender()
      this.showDropList = false
      let dateRange = DateUtil.getStartAndEndDateByWeekNum(this.weekValue)
      this.$emit('change', this.weekValue, dateRange)
    },
    //年改变
    yearChangeHandler(step) {
      if(!this.checkYearEnable(this.selYear+step)){
        return false
      }
      this.selYear += step
      this.calendarRender()
    },
    //月改变
    monthChangeHandler(index) {
      if (!this.checkMonthEnable(index,true)) {
        return false
      }
      this.selMonth = index
      this.calendarRender()
    },
    //周改变
    weekChangeHandler(item) {
      if (!this.checkWeekEnable(item.weekVal,true)) {
        return false
      }
      this.weekValue = item.weekVal
      this.showDropList = false
      let dateRange = DateUtil.getStartAndEndDateByWeekNum(this.weekValue)
      this.$emit('change', this.weekValue, dateRange)
    },
    //检查年是否超出范围
    checkYearEnable(year) {
      if (this.maxWeek.length > 1) {
        if(year > this.maxWeek[0]){
          if(this.maxMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      if (this.minWeek.length > 1) {
        if(year < this.minWeek[0]){
          if(this.minMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    },
    //检查周是否超出范围
    checkWeekEnable(weekVal,showMsg) {
      let year = weekVal[0]
      let week = weekVal[1]
      week = week<10 ? '0'+week : week
      let curStr = year+''+week
      if (this.maxWeek.length > 1) {
        let maxYear = this.maxWeek[0]
        let maxWeek = this.maxWeek[1]
        maxWeek = maxWeek < 10 ? '0'+maxWeek : maxWeek
        let maxStr = maxYear+''+maxWeek
        if(+curStr > +maxStr){
          if(this.maxMsg && showMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      
      if (this.minWeek.length > 1) {
        let minYear = this.minWeek[0]
        let minWeek = this.minWeek[1]
        minWeek = minWeek<10 ? '0'+minWeek : minWeek
        let minStr = minYear+''+minWeek
        if(+curStr < +minStr){
          if(this.minMsg && showMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    },
    //检查月是否超出范围
    checkMonthEnable(index,showMsg) {
      if (this.maxWeek.length > 1) {
        let maxWeek = DateUtil.getStartAndEndDateByWeekNum(this.maxWeek).startDate
        let maxWeekTime = new Date(maxWeek).getTime()
        let curMonthTime = new Date(this.selYear + '/' + (index+1) + '/01 00:00:00').getTime()
        if (curMonthTime > maxWeekTime) {
          if(this.maxMsg && showMsg) this.$toast(this.maxMsg)
          return false
        }
      }
      if (this.minWeek.length > 1) {
        let minWeek = DateUtil.getStartAndEndDateByWeekNum(this.minWeek).endDate
        let minDateTime = new Date(minWeek).getTime()
        let curSelWeekLastDay = DateUtil.getStartAndEndDateByMonth([this.selYear,(index+1)]).endDate
        let curMonthTime = new Date(curSelWeekLastDay + ' 00:00:00').getTime()
        if (curMonthTime < minDateTime) {
          if(this.minMsg && showMsg) this.$toast(this.minMsg)
          return false
        }
      }
      return true
    }
  }
}
</script>

<style scoped lang="less">
//引入mixin和var
@import '../../../css/mixin.less';
.v-week-picker {
  height: 44px;
  padding-left: 15px;
  padding-right: 15px;
  justify-content: center;
  align-items: center;
  display: flex;
  background-color: #fff;
  &-droplist {
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(0, 0, 0, 0.1);
    position: fixed;
    z-index: 2;
    &-header {
      background-color: #fff;
      position: relative;
      height: 50px;
      display: flex;
      font-size: 13px;
      background-color: #f7f7f7;
      .hairline(bottom, #eee);
    }
    &-yearhandler {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-right: 10px;
    }
    &-monthhandler {
      flex: 1;
      white-space: nowrap;
      overflow-x: auto;
      overflow-y: hidden;
      -webkit-overflow-scrolling: touch;
      .month-item {
        width: 48px;
        display: inline-block;
        height: 48px;
        justify-content: center;
        line-height: 48px;
        color: #333;
        text-align: center;
        &.disabled {
          opacity: 0.4;
          &:active {
            color: #333;
          }
        }
        &:active {
          color: @color-primary;
        }
        &.active {
          color: @color-primary;
          font-weight: bold;
        }
      }
    }
    &-content {
      background-color: #fff;
    }
  }
  &-header {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    &__label {
      font-size: 14px;
      display: flex;
      height: 100%;
      justify-content: center;
      align-items: center;
      &:active {
        opacity: 0.8;
      }
    }
    &__prev {
      transform: rotate(180deg);
    }
    &__prev,
    &__next {
      display: flex;
      width: 44px;
      height: 44px;
      justify-content: center;
      align-items: center;
      color: #999;
      font-size: 16px;
      &.disabled {
        opacity: 0.3;
      }
      &:active {
        background-color: #fafafa;
      }
    }
  }
}
.calendar-row {
  display: flex;
  &:active {
    opacity: 0.5;
  }
  &.active {
    background-color: @color-primary;
    &:active {
      opacity: 1;
    }
    li {
      color: #fff;
      font-weight: 500;
      &.week-value {
        color: #fff;
        font-weight: normal;
        border-color: lighten(@color-primary, 3%);
      }
    }
  }
  &-header {
    border-bottom: solid 1px #f3f3f3;

    &:active {
      opacity: 1;
    }
    li {
      color: #aaa;
      font-weight: bold;
    }
  }
  li {
    flex: 1;
    display: flex;
    font-size: 12px;
    justify-content: center;
    align-items: center;
    height: 48px;
    &.day-cell {
      font-size: 14px;
    }
    &.week-value {
      color: #999;
      border-right: solid 1px #f3f3f3;
    }
    &.disabled {
      opacity: 0.2;
    }
  }
}
</style>
